From 6d5ba9590b81ef9906a7e93f57c48edb78130f22 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 18 Jun 2021 14:46:24 +0200 Subject: [PATCH] x11: Get Visual from EGL directly Query the EGL_VISUAL_ID from the egl Config and select a config with the matching Visual. This is currently broken on Mesa because it does not expose any RGBA X Visuals in any EGL config, so we always end up with opaque Windows. https://gitlab.freedesktop.org/mesa/mesa/-/issues/149 --- gdk/x11/gdkdisplay-x11.c | 2 +- gdk/x11/gdkdisplay-x11.h | 3 - gdk/x11/gdkglcontext-egl.c | 131 ++++++++++++++++++++++++++++++++++--- 3 files changed, 124 insertions(+), 12 deletions(-) diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 5ee8843636..df893c0bbc 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -1335,7 +1335,7 @@ set_sm_client_id (GdkDisplay *display, gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID")); } -void +static void gdk_x11_display_query_default_visual (GdkX11Display *self, Visual **out_visual, int *out_depth) diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h index f4c177ce56..9960bc8e60 100644 --- a/gdk/x11/gdkdisplay-x11.h +++ b/gdk/x11/gdkdisplay-x11.h @@ -174,9 +174,6 @@ struct _GdkX11DisplayClass const XEvent *event); }; -void gdk_x11_display_query_default_visual (GdkX11Display *self, - Visual **out_visual, - int *out_depth); void _gdk_x11_display_error_event (GdkDisplay *display, XErrorEvent *error); gsize gdk_x11_display_get_max_request_size (GdkDisplay *display); diff --git a/gdk/x11/gdkglcontext-egl.c b/gdk/x11/gdkglcontext-egl.c index 61cabceb16..fa795cec2e 100644 --- a/gdk/x11/gdkglcontext-egl.c +++ b/gdk/x11/gdkglcontext-egl.c @@ -101,14 +101,55 @@ gdk_x11_display_create_egl_display (GdkX11Display *self) self->egl_display = eglGetDisplay ((EGLNativeDisplayType) dpy); } +static XVisualInfo * +gdk_x11_display_get_visual_info_for_visual (GdkX11Display *self, + VisualID visualid) +{ + XVisualInfo template, *visinfo; + int nvisuals; + + template.screen = self->screen->screen_num; + template.visualid = visualid; + + visinfo = XGetVisualInfo (gdk_x11_display_get_xdisplay (GDK_DISPLAY (self)), + VisualScreenMask | VisualIDMask, + &template, + &nvisuals); + g_warn_if_fail (nvisuals == 1); + + return visinfo; +} + +static gboolean +visual_is_rgba (XVisualInfo *visinfo) +{ + return + visinfo->depth == 32 && + visinfo->visual->red_mask == 0xff0000 && + visinfo->visual->green_mask == 0x00ff00 && + visinfo->visual->blue_mask == 0x0000ff; +} + #define MAX_EGL_ATTRS 30 static void -gdk_x11_display_create_egl_config (GdkX11Display *display) +gdk_x11_display_create_egl_config (GdkX11Display *display, + Visual **out_visual, + int *out_depth) { GdkX11Display *self = GDK_X11_DISPLAY (display); EGLint attrs[MAX_EGL_ATTRS]; - EGLint count; + EGLConfig *configs; + EGLint count, alloced; + enum { + NO_VISUAL_FOUND, + WITH_MULTISAMPLING, + WITH_STENCIL_AND_DEPTH_BUFFER, + NO_ALPHA, + NO_ALPHA_VISUAL, + PERFECT + } best_features; + int i = 0; attrs[i++] = EGL_SURFACE_TYPE; @@ -129,9 +170,85 @@ gdk_x11_display_create_egl_config (GdkX11Display *display) attrs[i++] = EGL_NONE; g_assert (i < MAX_EGL_ATTRS); - /* Pick first valid configuration that the driver returns us */ - if (!eglChooseConfig (self->egl_display, attrs, &display->egl_config, 1, &count) && count >= 1) - display->egl_config = NULL; + if (!eglChooseConfig (self->egl_display, attrs, NULL, -1, &alloced)) + return; + + configs = g_new (EGLConfig, alloced); + if (!eglChooseConfig (self->egl_display, attrs, configs, alloced, &count)) + { + g_free (configs); + return; + } + g_warn_if_fail (alloced == count); + + best_features = NO_VISUAL_FOUND; + + for (i = 0; i < count; i++) + { + XVisualInfo *visinfo; + int tmp, visualid; + + if (!eglGetConfigAttrib (self->egl_display, configs[i], EGL_NATIVE_VISUAL_ID, &visualid)) + continue; + + visinfo = gdk_x11_display_get_visual_info_for_visual (self, visualid); + if (visinfo == NULL) + continue; + + if (!eglGetConfigAttrib (self->egl_display, configs[i], EGL_SAMPLE_BUFFERS, &tmp) || tmp != 0) + { + if (best_features < WITH_MULTISAMPLING) + { + GDK_NOTE (OPENGL, g_message ("Best EGL config is %u for visual 0x%lX with multisampling", i, visinfo->visualid)); + best_features = WITH_MULTISAMPLING; + *out_visual = visinfo->visual; + *out_depth = visinfo->depth; + self->egl_config = configs[i]; + } + XFree (visinfo); + continue; + } + + if (!eglGetConfigAttrib (self->egl_display, configs[i], EGL_DEPTH_SIZE, &tmp) || tmp != 0 || + !eglGetConfigAttrib (self->egl_display, configs[i], EGL_STENCIL_SIZE, &tmp) || tmp != 0) + { + GDK_NOTE (OPENGL, g_message ("Best EGL config is %u for visual 0x%lX with stencil or depth buffer", i, visinfo->visualid)); + if (best_features < WITH_STENCIL_AND_DEPTH_BUFFER) + { + best_features = WITH_STENCIL_AND_DEPTH_BUFFER; + *out_visual = visinfo->visual; + *out_depth = visinfo->depth; + self->egl_config = configs[i]; + } + XFree (visinfo); + continue; + } + + if (!visual_is_rgba (visinfo)) + { + GDK_NOTE (OPENGL, g_message ("Best EGL config is %u for visual 0x%lX without RGBA Visual", i, visinfo->visualid)); + if (best_features < NO_ALPHA_VISUAL) + { + best_features = NO_ALPHA_VISUAL; + *out_visual = visinfo->visual; + *out_depth = visinfo->depth; + self->egl_config = configs[i]; + } + XFree (visinfo); + continue; + } + + GDK_NOTE (OPENGL, g_message ("EGL Config %u for visual 0x%lX is the perfect choice", i, visinfo->visualid)); + *out_visual = visinfo->visual; + *out_depth = visinfo->depth; + self->egl_config = configs[i]; + XFree (visinfo); + /* everything is perfect */ + best_features = PERFECT; + break; + } + + g_free (configs); } #undef MAX_EGL_ATTRS @@ -478,7 +595,7 @@ gdk_x11_display_init_egl (GdkX11Display *self, return FALSE; } - gdk_x11_display_create_egl_config (self); + gdk_x11_display_create_egl_config (self, out_visual, out_depth); if (self->egl_config == NULL) { eglTerminate (self->egl_display); @@ -515,8 +632,6 @@ gdk_x11_display_init_egl (GdkX11Display *self, self->has_egl_swap_buffers_with_damage ? "yes" : "no", self->has_egl_surfaceless_context ? "yes" : "no")); - gdk_x11_display_query_default_visual (self, out_visual, out_depth); - return TRUE; } -- 2.30.2